package app

import (
	"APT/internal/dao"
	"APT/internal/library/contexts"
	"APT/internal/model"
	"APT/internal/model/entity"
	"APT/utility/uuid"
	"context"
	"database/sql"
	"errors"
	"fmt"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"

	"github.com/gogf/gf/v2/errors/gerror"

	"APT/api/app/basics"
)

func (c *ControllerBasics) BrokerageList(ctx context.Context, req *basics.BrokerageListReq) (res *basics.BrokerageListRes, err error) {
	var (
		MemberInfo *entity.PmsMember
	)
	if err = dao.PmsMember.Ctx(ctx).Where(g.MapStrAny{
		dao.PmsMember.Columns().StaffId:   req.StaffId,
		dao.PmsMember.Columns().ChannelId: req.ChannelId,
	}).OmitEmptyWhere().Scan(&MemberInfo); err != nil {
		return
	}
	if g.IsEmpty(MemberInfo) {
		err = gerror.New("会员信息不存在")
		return
	}
	res = new(basics.BrokerageListRes)
	if err = dao.PmsAppStay.Ctx(ctx).Where(g.MapStrAny{
		dao.PmsAppStay.Columns().Referrer:     MemberInfo.Id,
		dao.PmsAppStay.Columns().RebateStatus: req.RebateStatus,
	}).OmitEmptyWhere().Page(req.PageNum, req.PageSize).ScanAndCount(&res.List, &res.Count, false); err != nil && !errors.Is(err, sql.ErrNoRows) {
		err = gerror.New("列表信息异常")
		return
	}
	for k, v := range res.List {
		if v.RebateStatus == "WAIT" {
			res.List[k].RebateAmount += v.OrderAmount * (v.RebateRate / 100)
		}
	}
	return
}
func (c *ControllerBasics) BrokerageDetail(ctx context.Context, req *basics.BrokerageDetailReq) (res *basics.BrokerageDetailRes, err error) {
	res = new(basics.BrokerageDetailRes)
	if err = dao.PmsAppStay.Ctx(ctx).Where("id", req.ID).Scan(&res); err != nil {
		return
	}
	return
}
func (c *ControllerBasics) BrokerageWithdrawBase(ctx context.Context, req *basics.BrokerageWithdrawBaseReq) (res *basics.BrokerageWithdrawBaseRes, err error) {
	var (
		Channel    *entity.PmsChannel
		Staff      *entity.PmsStaff
		MemberInfo *model.MemberIdentity
	)
	MemberInfo = contexts.GetMemberUser(ctx)
	res = new(basics.BrokerageWithdrawBaseRes)
	if req.ChannelId > 0 && MemberInfo.RebateMode == "CHANNEL" {
		if err = dao.PmsChannel.Ctx(ctx).Where(g.MapStrAny{
			dao.PmsChannel.Columns().Id: req.ChannelId,
		}).OmitEmptyWhere().Scan(&Channel); err != nil {
			return
		}
		res.MinWithdrawalAmount = Channel.MinWithdrawalAmount
		res.Balance = Channel.Balance
		res.ServiceCharge = Channel.ServiceCharge
		res.AfterDay = Channel.AfterDay
	} else if req.StaffId > 0 && MemberInfo.RebateMode == "STAFF" {
		if err = dao.PmsStaff.Ctx(ctx).Where(g.MapStrAny{
			dao.PmsStaff.Columns().Id: req.StaffId,
		}).OmitEmptyWhere().Scan(&Staff); err != nil {
			return
		}
		res.MinWithdrawalAmount = Staff.MinWithdrawalAmount
		res.Balance = Staff.Balance
		res.ServiceCharge = Staff.ServiceCharge
		res.AfterDay = Staff.AfterDay
	} else {
		err = gerror.New("参数错误")
	}
	return
}
func (c *ControllerBasics) BrokerageWithdraw(ctx context.Context, req *basics.BrokerageWithdrawReq) (res *basics.BrokerageWithdrawRes, err error) {
	var (
		Staff       *entity.PmsStaff
		Channel     *entity.PmsChannel
		ChannelType string
		insertId    int64
		rate        float64
		MemberInfo  *model.MemberIdentity
	)
	res = new(basics.BrokerageWithdrawRes)
	MemberInfo = contexts.GetMemberUser(ctx)
	if req.ChannelId > 0 && MemberInfo.RebateMode == "CHANNEL" {
		ChannelType = "CHANNEL"
		if err = dao.PmsChannel.Ctx(ctx).Where(g.MapStrAny{
			dao.PmsChannel.Columns().Id: req.ChannelId,
		}).OmitEmptyWhere().Scan(&Channel); err != nil {
			return
		}

		if Channel.Balance < req.Amount {
			err = gerror.New("申请提现金额不足")
			return
		}

		res.AfterDay = Channel.AfterDay
		rate = Channel.ServiceCharge
	} else if req.StaffId > 0 && MemberInfo.RebateMode == "STAFF" {
		ChannelType = "STAFF"
		if err = dao.PmsStaff.Ctx(ctx).Where(g.MapStrAny{
			dao.PmsStaff.Columns().Id: req.StaffId,
		}).OmitEmptyWhere().Scan(&Staff); err != nil {
			return
		}

		if Staff.Balance < req.Amount {
			err = gerror.New("申请提现金额不足")
			return
		}

		res.AfterDay = Staff.AfterDay
		rate = Staff.ServiceCharge
	} else {
		err = gerror.New("参数错误")
	}

	if err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
		// 减少渠道、员工余额，增加提现中金额
		if ChannelType == "CHANNEL" {
			if _, err = dao.PmsChannel.Ctx(ctx).TX(tx).OmitEmptyData().Where("id", req.ChannelId).Data(g.MapStrAny{
				dao.PmsChannel.Columns().Balance:              gdb.Raw(fmt.Sprintf("balance-%f", req.Amount)),
				dao.PmsChannel.Columns().ApplyWithdrawBalance: gdb.Raw(fmt.Sprintf("apply_withdraw_balance+%f", req.Amount)),
			}).Update(); err != nil {
				return
			}
		} else if ChannelType == "STAFF" {
			if _, err = dao.PmsStaff.Ctx(ctx).TX(tx).OmitEmptyData().Where("id", req.StaffId).Data(g.MapStrAny{
				dao.PmsStaff.Columns().Balance:              gdb.Raw(fmt.Sprintf("balance-%f", req.Amount)),
				dao.PmsStaff.Columns().ApplyWithdrawBalance: gdb.Raw(fmt.Sprintf("apply_withdraw_balance+%f", req.Amount)),
			}).Update(); err != nil {
				return
			}
		}

		// 写入提现记录
		if insertId, err = dao.PmsWithdraw.Ctx(ctx).TX(tx).OmitEmptyData().Data(&entity.PmsWithdraw{
			Type:           ChannelType,
			StaffId:        req.StaffId,
			ChannelId:      req.ChannelId,
			WithdrawAmount: req.Amount,
			WithdrawSn:     uuid.CreateOrderCode("W"),
			ServiceCharge:  rate,
			ArrivalAmount:  req.Amount - (req.Amount * (rate / 100)),
		}).InsertAndGetId(); err != nil {
			return
		}
		if g.IsEmpty(insertId) {
			err = gerror.New("提现申请失败")
			return
		}
		res.Amount = req.Amount
		res.Balance = req.Amount - (req.Amount * (rate / 100))
		res.ServiceCharge = rate
		res.CreateTime = gtime.Now()
		return
	}); err != nil {
		return
	}
	return
}
func (c *ControllerBasics) BrokerageWithdrawList(ctx context.Context, req *basics.BrokerageWithdrawListReq) (res *basics.BrokerageWithdrawListRes, err error) {
	res = new(basics.BrokerageWithdrawListRes)

	mod := dao.PmsWithdraw.Ctx(ctx).OrderDesc("id")

	if !g.IsEmpty(req.StaffId) {
		mod = mod.Where(dao.PmsWithdraw.Columns().StaffId, req.StaffId)
	}
	if !g.IsEmpty(req.ChannelId) {
		mod = mod.Where(dao.PmsWithdraw.Columns().ChannelId, req.ChannelId)
	}
	if !g.IsEmpty(req.WithdrawStatus) {
		mod = mod.Where(dao.PmsWithdraw.Columns().WithdrawStatus, req.WithdrawStatus)
	}
	if !g.IsEmpty(req.PageNum) {
		mod = mod.Page(req.PageNum, req.PageSize)
	}
	if err = mod.OmitEmptyWhere().ScanAndCount(&res.List, &res.Count, false); err != nil {
		return
	}
	return
}
func (c *ControllerBasics) BrokerageWithdrawDetail(ctx context.Context, req *basics.BrokerageWithdrawDetailReq) (res *basics.BrokerageWithdrawDetailRes, err error) {
	res = new(basics.BrokerageWithdrawDetailRes)
	if err = dao.PmsWithdraw.Ctx(ctx).Where("id", req.ID).Scan(&res); err != nil {
		return
	}

	switch res.WithdrawStatus {
	case "WAIT":
		res.Schedule = append(res.Schedule, &basics.BrokerageWithdrawSchedule{
			Des:    "提交申请待审核",
			Time:   res.CreatedAt,
			Remark: "",
		})
	case "SUCCESS":
		res.Schedule = append(res.Schedule, &basics.BrokerageWithdrawSchedule{
			Des:    "提交申请待审核",
			Time:   res.CreatedAt,
			Remark: "",
		})
		res.Schedule = append(res.Schedule, &basics.BrokerageWithdrawSchedule{
			Des:    "提现申请已通过",
			Time:   res.ApplyAt,
			Remark: res.ApplyRemark,
		})
		if res.Transfer == 2 {
			res.Schedule = append(res.Schedule, &basics.BrokerageWithdrawSchedule{
				Des:    "提现打款已处理",
				Time:   res.UpdatedAt,
				Remark: "",
			})
		}
	case "FAIL":
		res.Schedule = append(res.Schedule, &basics.BrokerageWithdrawSchedule{
			Des:    "提交申请待审核",
			Time:   res.CreatedAt,
			Remark: "",
		})
		res.Schedule = append(res.Schedule, &basics.BrokerageWithdrawSchedule{
			Des:    "提交失败申请被驳回",
			Time:   res.ApplyAt,
			Remark: res.ApplyRemark,
		})
	}
	return
}
